/**
 * NOTA:
 * [curDir] - com o caminho completo ex: c:\streetracer\lol
 * [lstDir] - com a letra mais : ex: c: d: a:
 *
 *
 * LINKS PARA CRIAR O INTERPRETADOR:
 * http://www.javaworld.com/javaworld/jw-07-1997/jw-07-indepth.html?page=1
 * http://www.javaworld.com/javaworld/jw-06-1997/jw-06-indepth.html?page=1
 * http://www.javaworld.com/javaworld/jw-07-2007/jw-07-awscripting1.html?page=1
 * http://www.javaworld.com/javaworld/jw-07-2007/images/01fig02.jpg
 *
 * Fases do interpretador [acho que é esta a ordem]
 * 1º - http://pt.wikipedia.org/wiki/An%C3%A1lise_l%C3%A9xica
 * 3º - http://pt.wikipedia.org/wiki/An%C3%A1lise_sem%C3%A2ntica ??? acho que pode nao ser preciso fazer isto
 *
 * A adicionar no interpretador
 * http://pt.wikipedia.org/wiki/Tokens
 * http://en.wikipedia.org/wiki/Token_(parser)
 *
 * http://pt.wikipedia.org/wiki/Express%C3%B5es_regulares
 *
 * http://pt.wikipedia.org/wiki/Parser
 * http://en.wikipedia.org/wiki/Parsing
 *
 * http://pt.wikipedia.org/wiki/Interpretador
 * http://en.wikipedia.org/wiki/Interpreter_(computing)
 *
 * http://pt.wikipedia.org/wiki/Analisador_sint%C3%A1tico_LL
 * http://en.wikipedia.org/wiki/LL_parser
 *
 * http://pt.wikipedia.org/wiki/Analisador_sint%C3%A1tico_LR
 * http://en.wikipedia.org/wiki/LR_parser
 *
 * http://pt.wikipedia.org/wiki/An%C3%A1lise_sint%C3%A1tica_sem_varredura
 */

/*
24/Fev/2009, 8:29:22
*/

package StreetRacerCommandLine;

import StreetRacerBASIC.BASICMain;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 * @author Street Racer
 */
public class CommandLineInterpreter {
    public CommandLineWindow commandWindow; // cria o objecto para estar disponivel na class inteira

    // ### [DIR] variaveis ###
    int startDir = 0; // variavel para saber se o dir já foi iniciado e inicializa a variavel
    String curDir; // variavel para saber em que DIR está
    String lstDir[] = new String[26]; // variavel com a lista de drives
    int numDir = -1; // variavel para saber quantos discos existem e inicializa NOTA: começa a contagem em [0]
    // ### [DIR] Fim ###

    public CommandLineInterpreter(CommandLineWindow nomeObj) {
        this.commandWindow = nomeObj; // coloca o objecto disponivel na class inteira
    }

    /**
     * Recebe o comando
     * @param command
     */
    public void getCommand (String line) throws IOException {
        //String convLine; // guarda a linha convertida para maiusculas XXX acho que nao é necessario
        String convCommand[] = new String[7]; // variavel que fica com os varios comandos escritos
        int lenLine; // variavel para saber o tamanho da linha
        char tempChar; // variavel temporaria
        char tempAntChar = 0; // guarda o caratere anterior
        int countCommand = 0; // variavel para contar o n de palavras e inicializa

        lenLine = line.length(); // ve o tamanho da linha

        // faz um ciclo para separar os comandos
        for (int i = 0; i < lenLine; i++) {
            tempChar = line.charAt(i); // le o caratere

            if (tempChar == ' ') { // verifica se contem espaço
                if (countCommand == 0); // verifica se já colocou alguma palavra
                else {
                    if (tempAntChar == ' ');// verifica se o caratere anterior ja era um espaço
                }
            }
            else {
                if (countCommand == 0) { // verifica se já foi adicionada alguma palavra
                    countCommand++; // auto incrementa
                    convCommand[countCommand] = String.valueOf(tempChar); // adiciona o caratere
                }
                else if (tempAntChar == ' ') { // ve se o caratere anterior é um espaço
                    countCommand++; // auto incrementa
                    convCommand[countCommand] = String.valueOf(tempChar); // adiciona o caratere
                }
                else {
                    convCommand[countCommand] = convCommand[countCommand] + String.valueOf(tempChar); // adiciona o caratere
                }
            }
            
            tempAntChar = tempChar;

        }

        // verifica se algum comando foi introduzido
        if (countCommand == 0); // ignora

        else { // ve se o comando existe

            convCommand[1] = convCommand[1].toUpperCase(); // converte o 1º comando para letra maiuscula

            if (convCommand[1].equals("HELP")) {           //HELP
                help();
            }
            else if (convCommand[1].equals("?")) {         //?
                help();
            }
            else if (convCommand[1].equals("DIR")) {       //DIR
                dir();
            }
            else if (convCommand[1].equals("CD")) {        //CD
                cd(convCommand[2]);
            }
            else if (convCommand[1].equals("MKDIR")) {     //MKDIR
                mkdir(convCommand[2]);
            }
            else if (convCommand[1].equals("INFO")) {      //INFO
                info(convCommand[2]);
            }
            else if (convCommand[1].equals("TIME")) {      //TIME
                time();
            }
            else if (convCommand[1].equals("DATE")) {      //DATE
                date();
            }
            else if (convCommand[1].equals("ECHO")) {
                echo(convCommand[2]);                      //ECHO
            }
            else if (convCommand[1].equals("CLS")) {       //CLS
                cls();
            }
            else if (convCommand[1].equals("EXEC")) {      //EXEC
                exec(convCommand[2]);
            }
            else if (convCommand[1].equals("EXIT")) {      //EXIT
                exit();
            }
            else {
                commandDesc();
            }
        }
    }


    /**
     * Comando: HELP (Ajuda)
     *
     */
    private void help() {
        commandWindow.appendTextArea("[ Ajuda ]\n");
        commandWindow.appendTextArea("Street Racer Command Line - v 0.0.3 - BUILD \n");
        commandWindow.appendTextArea("Data da compilação: 10-Mar-2009\n");
        commandWindow.appendTextArea("Updates em -> www.StreetRacerBlog.BlogSpot.com <-\n");
        commandWindow.appendTextArea("----------\n\n");

        commandWindow.appendTextArea("HELP  - Exibe a ajuda\n");
        commandWindow.appendTextArea("TIME  - Exibe a hora actual\n");
        commandWindow.appendTextArea("DATE  - Exibe a data actual\n");
        commandWindow.appendTextArea("DIR   - Faz a listagem do directorio especificado\n");
        commandWindow.appendTextArea("CD    - Escolhe o directorio especificado\n");
        commandWindow.appendTextArea("MKDIR - Cria uma pasta no caminho especificado\n");
        commandWindow.appendTextArea("CLS   - Limpa o conteudo da linha de comandos\n");
        commandWindow.appendTextArea("EXIT  - Termina a linha de comandos\n");
        commandWindow.appendTextArea("INFO  - Exibe as informações de um ficheiro ou pasta");
    }

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // XXX nalgum sitio quando se escreve o nome da pastas por exemplo no [CD]
    // XXX o nome da pasta fica para lowercase
    // XXX ver onde está o erro para ficar igual como o nome da pasta
    // XXX ou se automaticamente o java faz isso <--- VER
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    /**
     * Comando: DIR
     * Retorna a listagem dos ficheiros
     */
    private void dir() {

        if (startDir == 0){// verifica se a lista de drives já foi iniciada
            startDir(); // inicia a detecção das drives
        }

        // verifica se o directorio ja foi especificado
        if (curDir == null) { // faz a listagem dos discos
            commandWindow.appendTextArea("Disco não especificado\n\n");
            commandWindow.appendTextArea("Lista dos discos\n");
            commandWindow.appendTextArea("----------------\n");

            // verifica se existe algum disco
            if (numDir == -1) { // diz que nao tem discos
                commandWindow.appendTextArea("Não existem discos instalados");
            }
            else { // mostra a lista dos discos
                for (int i=0; i<=numDir; i++) {
                    commandWindow.appendTextArea(lstDir[i] + "\\\n");
                }
                commandWindow.appendTextArea("Dica: Utilize o comando: [CD] para escolher o disco");
            }

        } else { // faz a listagem do directorio normalmente
            String curDirR; // variavel com o directorio corrente sem os [:]

            curDirR = removeDoisPontos(curDir); // remove os [:]

            File dir = new File(System.getProperty("user.dir") + "\\" + curDirR); // ve qual onde esta o programa

            String[] dirList = dir.list(); // le os ficheiros

            // verifica se a pasta tem alguma coisa
            if (dirList.length == 0) {
                commandWindow.appendTextArea("Directório vazio");
            }
            else {

                int numFiles = 0; // conta o numero de ficheiros

                commandWindow.appendTextArea("Listagem de " + curDir + "\n\n");
                commandWindow.appendTextArea("TIPO  TAMANHO  NOME\n");

                for (int i=0; i<dirList.length; i++) { // faz a listagem dos ficheiros
                    String addText = null;
                    boolean type; // variavel para saber se é directorio
                    String fileSize; // variavel para saber o tamanho do ficheiro
                    int len; // saber o num de carateres
                    int numSpaces; // saber o num de espaços

                    File ficheiro = new File(System.getProperty("user.dir") + "\\" + curDirR + "\\" + dirList[i]);

                    type = ficheiro.isDirectory(); // ve se é directorio
                    if (type == true) { // se for directorio
                        addText = "[DIR]";
                        fileSize = "        ";
                    }
                    else { // se for ficheiro
                        numFiles++; //auto incrementa
                        addText = "     ";
                        fileSize = Long.toString(ficheiro.length());
                        len = fileSize.length(); // sabe o tamanho
                        numSpaces = 8 - len; // sabe quantos espaços a dar

                         // verifica se nao é preciso espaços
                        if (numSpaces == 0);
                        else {
                            //faz um ciclo para adicionar os espaços necessarios
                            for (int i2 = 1; i2 <= numSpaces; i2++) {
                                fileSize = fileSize + " ";
                            }
                        }
                    }

                    commandWindow.appendTextArea(addText + " " + fileSize + " " + dirList[i] + "\n"); // coloca a lista na linha de comandos
                }

                commandWindow.appendTextArea("Número total de ficheiros: " + numFiles);

            }
        }        
    }

    /**
     * Inicia o comando dir
     */
    private void startDir() {
        String templist = null; // variavel temporaria
        boolean isFolder; // variavel para saber se é uma pasta

        File dir = new File(System.getProperty("user.dir")); // ve qual onde esta o programa

        String[] dirList = dir.list(); // le os ficheiros

        // XXX colocar aqui a verificar todos os tipos de letras possiveis (do abecedario)
        for (int i=0; i<dirList.length; i++) { // procura os discos disponiveis
            File folder = new File(System.getProperty("user.dir") + "\\" + dirList[i]); // inicia o objecto para saber se é uma pasta

            isFolder = folder.isDirectory(); // verifica se é uma pasta

            // se for uma pasta
            if (isFolder == true) {
                
                templist = dirList[i]; // coloca na variavel temporaria

                templist = templist.toLowerCase(); // coloca em letra pequena

                //verifica se é um nome válido
                if (templist.equals("a") || templist.equals("b") || templist.equals("c") || templist.equals("d") || templist.equals("e")) {
                    numDir++; // auto incrementa
                    lstDir[numDir] = templist + ":"; // adiciona a drive à lista
                }
                else if (templist.equals("f") || templist.equals("g") || templist.equals("h") || templist.equals("i") || templist.equals("j") || templist.equals("k")) {
                    numDir++; // auto incrementa
                    lstDir[numDir] = templist + ":"; // adiciona a drive à lista
                }
                else if (templist.equals("l") || templist.equals("m") || templist.equals("n") || templist.equals("o") || templist.equals("p") || templist.equals("q") || templist.equals("r") || templist.equals("s") || templist.equals("t") || templist.equals("u") || templist.equals("v") || templist.equals("w") || templist.equals("x") || templist.equals("y") || templist.equals("z")) {
                    numDir++; // auto incrementa
                    lstDir[numDir] = templist + ":"; // adiciona a drive à lista
                }
            }
        }

        startDir = 1; // diz que ja foi iniciado

        
    }

    // ### FIM Comando: DIR ###

    /**
     * Verifica se o disco especificado existe
     * @param caminho
     * @return
     */
    private boolean verfDisco(String caminho) {
        String splitedDir[] = new String[8]; // vector com o caminho separado
        int lenLine; /** variavel para saber o tamanho da linha */
        char tempChar; // variavel temporaria
        boolean validLetter; // variavel para saber se a letra é válida
        boolean validDisco = false; // variavel que retorna para saber se existe

        splitedDir = splitDir(caminho); // separa o caminho

        lenLine = splitedDir[0].length(); // ve o tamanho da linha

        if (lenLine == 2) { //verifica se tem 2 carateres
            tempChar = splitedDir[0].charAt(1); // ve o 2 caratere
            if (tempChar == ':') { // verifica se tem [:]
                tempChar = splitedDir[0].charAt(0); // le o 1 caratere

                tempChar = Character.toLowerCase(tempChar);

                //verifica se é um nome válido
                if (tempChar == 'a' || tempChar == 'b' || tempChar == 'c' || tempChar == 'd' || tempChar == 'e'){
                    validLetter = true;
                }
                else if (tempChar == 'f' || tempChar == 'g' || tempChar == 'h' || tempChar == 'i' || tempChar == 'j' || tempChar == 'k') {
                    validLetter = true;
                }
                else if (tempChar == 'l' || tempChar == 'm' || tempChar == 'n' || tempChar == 'o' || tempChar == 'p' || tempChar == 'q' || tempChar == 'r' || tempChar == 's' || tempChar == 't' || tempChar == 'u' || tempChar == 'v' || tempChar == 'w' || tempChar == 'x' || tempChar == 'y' || tempChar == 'z'){
                    validLetter = true;
                }
                else {
                    validLetter = false;
                }

                // verifica se a letra é valida
                if (validLetter = true) {
                    // faz um ciclo para ver se o disco existe
                    for (int i = 0; i <= numDir; i++) {
                        // verifica se o disco existe
                        if (splitedDir[0].equals(lstDir[i])) {
                            validDisco = true; // coloca que existe
                        }
                    }
                }
                else {
                    validDisco = false;
                }

            }
        }

        return validDisco;
    }

    /**
     * Verifica se a pasta especificada existe
     * @param caminho
     * @return
     */
    private boolean verfPasta(String caminho) {
        boolean validPasta = false; // variavel que retorna para saber se existe
        String splitedDir[] = new String [8]; // vector com o caminho separado
        String disco; // variavel para saber o disco
        int nivelPasta; // variavel para saber quantos niveis tem
        String caminhoIncre = ""; // variavel para incrementar o caminho e reseta
        boolean exists = false; // variavel para saber se existe

        boolean isPasta = false; // variavel para saber se é uma pasta
        splitedDir = splitDir(caminho); // separa o caminho

        disco = removeDoisPontos(splitedDir[0]); // remove os 2 [:] se tiver
        nivelPasta = Integer.parseInt(splitedDir[7]); // converte para int

        for (int i = 1; i <= nivelPasta; i++) {
            caminhoIncre = caminhoIncre + splitedDir[i] + "\\"; // incrementa a pasta

            File verDir = new File(System.getProperty("user.dir") + "\\" + disco + "\\" + caminhoIncre); // cria o objecto
            exists = verDir.exists(); // verfica se existe

            //verfica se existe
            if (exists == true) {
                isPasta = verDir.isDirectory(); // verifica se é uma pasta

                if (isPasta == true);
                else {
                    break;
                }
            }
            else {
                break;
            }
        }

        // verifica se a pasta existe
        if (exists == true & isPasta == true) {
            validPasta = true; // diz que o caminho é valido
        }

        return validPasta; // retorna o valor
    }

    /**
     * Remove os [:] do caminho
     * @param caminho
     * @return
     */
    private String removeDoisPontos (String caminho) {
        caminho = caminho.replaceAll(":", "");
        return caminho;
    }


    /**
     * Comando: CD
     * Muda de directorio
     * @param dir
     */
    private void cd(String dir) {
        //XXX NOTA: O caratere [.] é especial pois serve para subir de nivel directorio
        //XXX um ficheiro ou pasta nunca pode começar por [.]

        //XXX PS: tb nunca pode conter/começar com certos carates especiais <-- possivelmente criar um metodo que verifique isto

        //Variaveis
        int lenLine = 0; // variavel para saber o tamanho da linha
        char tempChar = 0; // variavel temporaria
        String splitedDir[] = new String[8]; // vector com o caminho separado
        String tempStr; // variavel temporaria        

       //verifica se a lista de drives já foi iniciada
       if (startDir == 0) { // inicia a lista de drives
           startDir(); // inicia a detecção das drives
       }

        // XXX COLOCAR AQUI A VERIFICAR SE O NIVEL DO DIRECTORIO NAO EXEDE 7 NIVEIS

        //verifica se nada foi escrito
        if (dir == null) {
            // verifica se ja escolheu algum directorio
            if (curDir != null) {
                commandWindow.appendTextArea("Directorio corrente: " + curDir); // mostra o directorio actual
            }
        }
        else {
                splitedDir = splitDir(dir); // separa o caminho

                if (splitedDir[0].equals("..")) {                                   //OPÇÃO [..]
                    if (curDir == null) {
                        commandWindow.appendTextArea("Não é possivel subir mais");
                    }
                    else {
                        String splitedDir2[] = new String[8]; // 2ª variavel para saber o caminho separado
                        splitedDir2 = splitDir(curDir); // separa o directorio actual
                        
                        // verifica qual o nivel em que está
                        if (splitedDir2[7].equals("0")) {                              // Nivel 0 (Desmonta)

                            curDir = null; // reseta o directorio actual
                            commandWindow.setDirName("");
                            commandWindow.appendTextArea("A drive " + splitedDir2[0] + "\\ foi desmontada");
                        }
                        else {                                                      // Nivel 1 ou mais (sobe)
                            int nivelPasta; // variavel para saber o nivel da pasta

                            nivelPasta = Integer.parseInt(splitedDir2[7]); // ve o nivel da pasta convertendo para int

                            curDir = ""; // reseta

                            // faz um ciclo ate a penultima pasta
                            for (int i = 0; i < nivelPasta; i++) {
                                curDir = curDir + splitedDir2[i] + "\\"; // actualiza o directorio actual
                            }
                            commandWindow.setDirName(curDir); // actualiza o directorio actual
                            commandWindow.appendTextArea("Subiu para o directorio " + curDir);
                        }
                    }
                }
                // verifica se ja escolheu algum directorio
                else if (splitedDir[0].equals(".")) {                               //OPÇÃO [.]
                    if (curDir != null) {
                        commandWindow.appendTextArea("Directorio corrente: " + curDir); // mostra o directorio actual
                    }
                }
                else {

                    // verifica se foi escrito
                    //if (splitedDir[0].equals("")) {
                    //    commandWindow.appendTextArea(curDir);
                    //}

                    if (splitedDir[7].equals("0")) { // verifica se só tem 1 nivel              //### 1 NIVEL (FEITO)
                        lenLine = splitedDir[0].length(); // ve o tamanho da linha

                    // verifica se tem 2 carateres
                    if (lenLine == 2) {
                        tempChar = splitedDir[0].charAt(1); //  le o 2 caratere
                    }

                    if (tempChar == ':') { // verifica se é uma drive                       //### DRIVE (FEITO)

                        boolean existsDisco; // variavel para saber se o disco existe

                        existsDisco = verfDisco(splitedDir[0]); // ve se o disco existe

                        if (existsDisco == true) {
                            curDir = splitedDir[0] + "\\"; // coloca o directorio na variavel do directorio corrente
                            commandWindow.setDirName(curDir); // coloca no CommandWindow o directorio actual
                            commandWindow.appendTextArea("Directorio alterado para " + curDir);
                        }
                        else {
                            commandWindow.appendTextArea("O directorio especificado nao existe");
                        }

                    }

                    else { // se nao                                                        //### PASTA (FEITO)

                        // XXX COLOCAR AQUI A VERIFICAR SE O NIVEL DO DIRECTORIO NAO EXEDE 7 NIVEIS

                        if (curDir != null) {
                            boolean exists;

                            exists = verfPasta(curDir + splitedDir[0]); //verifica se a pasta existe

                            if (exists == true) { // verifica se o o directorio existe
                                curDir = curDir + splitedDir [0] + "\\"; // actualiza o directorio actual
                                commandWindow.setDirName(curDir); // actualiza no CommandWindow o directorio actual
                                commandWindow.appendTextArea(("Directorio alterado para " + curDir));
                                }
                                else {
                                    commandWindow.appendTextArea("O directorio não existe");
                                }
                            }
                            else {
                                commandWindow.appendTextArea("O disco não foi especificado");
                            }

                    }

                }

                else {//entao tem mais de 1 nivel                                           //### MAIS DE 1 NIVEL

                    lenLine = splitedDir[0].length(); // ve o tamanho da linha

                    // verifica se tem 2 carateres
                    if (lenLine == 2) {
                        tempChar = splitedDir[0].charAt(1); //  le o 2 caratere
                    }

                    // verifica se é uma drive                                             //### DRIVE (FEITO)
                    if (tempChar == ':') {

                        // XXX COLOCAR AQUI A VERIFICAR SE O NIVEL DO DIRECTORIO NAO EXEDE 7 NIVEIS

                        boolean existsDisco; // Variavel para saber se o disco existe
                        int nivelPasta; // variavel para saber qual o nivel da pasta
                        boolean existsPasta = false; // variavel para saber se a pasta existe

                        existsDisco = verfDisco(splitedDir[0]); // ve se o disco existe

                        //verifica se o disco existe
                        if(existsDisco == true) {

                            nivelPasta = Integer.parseInt(splitedDir[7]); // converte para int
                            existsPasta = verfPasta(dir); // verifica se a pasta existe

                            // verifica se a pasta existe
                            if(existsPasta == true) {
                                curDir = ""; // reseta o directorio actual

                                // faz um ciclo para todas as pastas
                                for (int i = 0; i <= nivelPasta; i++) {
                                    curDir = curDir + splitedDir[i] + "\\"; // actualiza o directorio actual, auto incrementando
                                }
                                commandWindow.setDirName(curDir); // actualiza no CommandWindow o directorio actual
                                commandWindow.appendTextArea("Directorio alterado para " + curDir);
                            }
                            else {
                                commandWindow.appendTextArea("O caminho especificado é invalido");
                            }
                        }
                        else {
                            commandWindow.appendTextArea("O disco não existe");
                        }
                    }
            
                    // então sao pastas
                    else {                                                                 //### PASTAS (FEITO)
                        if (curDir != null) {
                            boolean exists = false; // saber se existe
                            int nivelPasta; // variavel para saber quantas subpastas existem

                            // XXX COLOCAR AQUI A VERIFICAR SE O NIVEL DO DIRECTORIO NAO EXEDE 7 NIVEIS

                            nivelPasta = Integer.parseInt(splitedDir[7]); // converte para int

                            exists = verfPasta(curDir + dir); // verifica se a pasta existe

                                if (exists == true) { // verifica se a pasta existe
                                    //faz um ciclo para todas as pastas
                                    for (int i = 0; i <= nivelPasta; i++) {
                                        curDir = curDir + splitedDir[i] + "\\"; // actualiza o directorio actual
                                    }
                                    commandWindow.setDirName(curDir); // actualiza no CommandWindow o directorio actual
                                    commandWindow.appendTextArea("Directorio alterado para " + curDir);
                                }
                                else {
                                    commandWindow.appendTextArea("O caminho especificado é inválido");
                                }
                        }
                        else {
                            commandWindow.appendTextArea("O disco nao foi especificado");
                        }
                    }
                }
            }
        }
    }

    /**
     * Retorna o caminho separado em pastas
     * @param line
     * @return
     * @see Limitado até pastas nivel 7
     */
    private String[] splitDir (String line) {
        String splitedDir[]= new String[8]; // cria o vector
        int lenLine; // variavel para saber o tamanho da linha
        char tempChar; // variavel temporaria
        char tempAntChar = 0; // guarda a variavel anterior
        int countDir = -1; //conta o numero de directorios (nivel)

        lenLine = line.length(); // ve o tamanho da linha

        // faz um ciclo para detectar as pastas
        for (int i = 0; i < lenLine; i++) {
            tempChar = line.charAt(i); // le o caratere

            if (tempChar == '\\' || tempChar == '/');
            else {
                if (countDir == -1) {
                    countDir++; // auto incrementa
                    splitedDir[countDir] = String.valueOf(tempChar); // adiciona o caratere
                }
                else if (tempAntChar == '\\' || tempAntChar == '/') { // ve se o caratere anterior é uma \ ou /
                    countDir++; //auto incrementa
                    splitedDir[countDir] = String.valueOf(tempChar); //adiciona o caratere
                }
                else {
                    splitedDir[countDir] = splitedDir[countDir] + String.valueOf(tempChar); // adiciona o caratere
                }
            }

            tempAntChar = tempChar; // coloca o char anterior
        }

        splitedDir[7] = String.valueOf(countDir); // coloca o numero de niveis

        return splitedDir; // retorna as pastas separadas
    }

    /**
     * Comando: MKDIR
     * Cria uma pasta
     * @param comando
     */
    private void mkdir(String comando) {

        // XXX COLOCAR AQUI A VERIFICAR SE O NIVEL DO DIRECTORIO NAO EXEDE 7 NIVEIS

        if (startDir == 0) { // verifica se a lista de drives ja foi iniciada
            startDir();
        }

        //XXX colocar a ver se o disco esta especificado e o caminho ex: c:\ajdka\akd - Feito
        //XXX ultima pasta ("akd") é o nome da nova pasta, e deve verificar se já existe - nao feito

        // verifica se nao foi especificado o caminho
        if (comando == null) {
            if (curDir != null) {
                commandWindow.appendTextArea("O nome da pasta não foi especificado");
            }
            else {
                commandWindow.appendTextArea("Disco não especificado");
            }
        }
        else {

            // verifica se o directorio nao foi especificado
            if (curDir == null) {
                commandWindow.appendTextArea("Disco não especificado");
            }
            else {
                String dirRem; // variavel com o caminho sem os [:]
                boolean existsPasta; // ve se já existe

                dirRem = removeDoisPontos(curDir);

                File mkDir = new File(System.getProperty("user.dir") + "\\" + dirRem + "\\" + comando); // inicia o objecto
                existsPasta = mkDir.exists();// ve se a pasta existe

                //verifica se a pasta existe
                if(existsPasta == false) {
                    mkDir.mkdir(); // cria a pasta

                    commandWindow.appendTextArea("A pasta " + comando + " foi criada com sucesso");
                }
                else{
                    commandWindow.appendTextArea("Uma pasta ou ficheiro já existe com esse nome");
                }
            }
        }
    }

    /**
     * Comando: INFO
     * Mostra informação do ficheiro / pasta detalhada
     * @param nFile
     */
    private void info(String nFile) {
        //XXX colocar a mostrar as informações do disco quando escolhido
        //XXX colocar a mostrar o tamanho total que ocupa a pasta, pesquisando pastas e subpastas

        //XXX acabar isto!!!!
        //XXX acabar isto!!!!
        //XXX acabar isto!!!!
        //XXX acabar isto!!!!

        // verifica se tem caminho
        if (curDir != null) {
            String splitedDir[] = new String[8]; // caminho separado
            int nivel; //saber o nivel da pasta
            String dirR; // variavel para saber o caminho sem os [:]

            // verifica se o ficheiro nao foi especificado
            if (nFile == null) { // mostra as informações da pasta
                String loc = ""; // saber onde está a pasta
                //long date; // variavel para saber a data da pasta
                boolean hidden; // variavel para saber se está oculto

                dirR = removeDoisPontos(curDir); // remove os [:]
                File myDir = new File(System.getProperty("user.dir") + dirR);

                //date = myDir.lastModified(); // sabe qual a data
                hidden = myDir.isHidden(); // sabe se está oculto

                splitedDir = splitDir(curDir); // separa o caminho actual
                nivel = Integer.parseInt(splitedDir[7]); // diz o nivel e converte para int

                // faz um ciclo para saber a localização da pasta
                for (int i = 0; i < nivel; i++) {
                    loc = loc + splitedDir[i] + "\\"; // incrementa
                }

                commandWindow.appendTextArea("Informações da Pasta\n");
                commandWindow.appendTextArea("--------------------\n\n");
                commandWindow.appendTextArea("Pasta:       " + splitedDir[nivel] + "\n");
                commandWindow.appendTextArea("Localização: " + loc);
                //commandWindow.appendTextArea("Data:  " + date + "\n");

                //commandWindow.appendTextArea("[");
                //verifica se esta oculto
                //if (hidden == false) {
                //    commandWindow.appendTextArea(" ");
                //}
                //else {
                //    commandWindow.appendTextArea("X");
                //}
                //commandWindow.appendTextArea("] Oculto \n");
            }
            else { // o ficheiro ou pasta esta especificado
                int lenLine; //variavel para saber o tamanho da linha
                char tempChar = 0; // variavel temporaria

                splitedDir = splitDir(nFile); // separa o caminho

                lenLine = splitedDir[0].length(); // ve o tamanho da linha

                //verifica se tem 2 carateres
                if (lenLine == 2) {
                    tempChar = splitedDir[0].charAt(1); // le o 2º caratere
                }

                if (tempChar == ':') { // verifica se é uma drive
                    boolean exists; // variavel para saber se o disco / pasta existe

                    exists = verfDisco(splitedDir[0]); // ve se o disco existe

                    // ve se o disco existe
                    if (exists == true) {

                        nivel = Integer.parseInt(splitedDir[7]); //ve o nivel e converte para int

                        //verifica se tem mais de 1 nivel
                        if (nivel < 0) {

                        }
                        else {// se nao
                            commandWindow.appendTextArea("Informações do disco\n");
                            commandWindow.appendTextArea("--------------------\n\n");
                            commandWindow.appendTextArea("Disco: " + splitedDir[0] + "\\");
                        }
                    }


            }
        }

    }
    }

    /**
     * Comando: TIME
     * Retorna as Horas actuais
     */
    private void time() {
        String timeStr;

        Date timeAll = new Date(); // cria o objecto para saber a data actual
        SimpleDateFormat timeFor = new SimpleDateFormat("HH:mm:ss"); // inicia e formata a data actual

        timeStr = timeFor.format(timeAll); //coloca e formata para String a data na variavel
        
        commandWindow.appendTextArea(timeStr);
    }


    /**
     * Comando: DATE
     * Retorna a Data actual
     */
    private void date() {
        String dateStr; // variavel a mostrar

        Date dateAll = new Date(); // cria o objecto para saber a data actual
        SimpleDateFormat dateFor = new SimpleDateFormat("dd-MM-yyyy"); // inicia e formata a data actual

        dateStr = dateFor.format(dateAll); //coloca e formata para String a data na variavel

        commandWindow.appendTextArea(dateStr);
    }

    /**
     * Comando: ECHO -texto
     * Imprime o texto especificado
     * @param text
     */
    private void echo(String text) {
        commandWindow.appendTextArea(text);
    }

    /**
     * Comando: CLS
     * Limpa o conteudo da linha de comandos
     */
    private void cls() {
        commandWindow.setTextArea("");
    }

    /**
     * Comando: EXIT
     * Termina a linha de comandos
     */
    private void exit() {
        System.exit(0); // termina o programa, a bem [1] a mal. (retorna o numero)
    }

    /**
     * Comando: EXEC
     * Executa o ficheiro
     */
    private void exec(String file) throws IOException {
        String fullPath; // variavel com o caminho completo
        String rPath; // variavel sem os [:]

        BASICMain start = new BASICMain(); // cria o objecto

        rPath = removeDoisPontos(curDir); // remove os 2 [:]
        fullPath = System.getProperty("user.dir") + "\\" + rPath + file; // da o caminho completo

        start.execute(fullPath); // inicia o executavel
    }

    /**
     * Método usado para quando o comando é desconhecido
     */
    private void commandDesc () {
        commandWindow.appendTextArea("Commando desconhecido! Use o comando HELP ou ? para ajuda");
    }

}
